﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PlatformNetCore.Common.Helper
{
    public class HttpHelper
    {
        #region 异步Get/Post请求
        /// <summary>
        /// HttpAsyncGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        public async static Task<TResponse> HttpAsyncGet<TResponse>(string url)
        {
            try
            {
                WebRequest request = WebRequest.Create(url);
                request.Method = "GET";
                request.ContentType = "application/json";
                StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream());
                string result = await sr.ReadToEndAsync();
                if (sr != null)
                {
                    sr.Close();
                }
                return JsonHelper.DeserializeObject<TResponse>(result);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                return default(TResponse);
            }
        }

        /// <summary>
        /// HttpAsyncGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        public async static Task<TResponse> HttpAsyncPost<TRequest, TResponse>(string url, TRequest request)
        {
            try
            {
                HttpClient client = new HttpClient();
                string jsonData = JsonHelper.SerializeObject(request);
                HttpContent content = new StringContent(jsonData, Encoding.UTF8);
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var task = await client.PostAsync(url, content);
                string result = await task.Content.ReadAsStringAsync();
                return JsonHelper.DeserializeObject<TResponse>(result);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                return default(TResponse);
            }
        }

        #endregion

        #region 同步Get/Post请求

        #region 通用Get请求
        /// <summary>
        /// HttpGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        public static string HttpGet(string title, string url, int retryTimes)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                return Get(url);
            }, url, string.Empty, retryTimes, () => Thread.Sleep(100));
        }

        /// <summary>
        /// HttpGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        private static string Get(string url)
        {
            WebRequest request = WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = "text/html";
            Encoding encoding = Encoding.UTF8;
            Stream stream = request.GetResponse().GetResponseStream();
            //获取响应内容  
            string response = string.Empty;
            using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream(), encoding))
            {
                response = reader.ReadToEnd();
                reader.Close();
                stream.Close();
            }
            return response;
        }

        /// <summary>
        /// HttpGet请求 返回 2 开头响应码
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        public static string HttpGet(string title, string url)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                WebRequest request = WebRequest.Create(url);
                request.Method = "GET";
                request.ContentType = "text/html";
                Encoding encoding = Encoding.UTF8;
                Stream stream = request.GetResponse().GetResponseStream();
                //获取响应内容  
                string responseStr = string.Empty;
                using (StreamReader reader = new StreamReader(stream, encoding))
                {
                    responseStr = reader.ReadToEnd();
                    reader.Close();
                    stream.Close();
                }
                return responseStr;
            }, url, string.Empty, 0, () => Thread.Sleep(200));
        }

        /// <summary>
        /// HttpGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        public static string HttpGet(string title, string url, Encoding encoding, int retryTimes)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                return Get(url, encoding);
            }, url, string.Empty, retryTimes, () => Thread.Sleep(100));
        }
        /// <summary>
        /// HttpGet请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requireHttp200"></param>
        /// <returns></returns>
        private static string Get(string url, Encoding encoding)
        {
            WebRequest request = WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = "text/html";
            Stream stream = request.GetResponse().GetResponseStream();
            //获取响应内容  
            string response = string.Empty;
            using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream(), encoding))
            {
                response = reader.ReadToEnd();
                reader.Close();
                stream.Close();
            }
            return response;
        }
        #endregion

        #region 通用请求
        /// <summary>
        /// HttpPost 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string HttpPost(string title, string url, string postdata, string contentType, int retryTimes)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                return Post(url, postdata, contentType);
            }, postdata, string.Empty, retryTimes, () => Thread.Sleep(100));
        }
        /// <summary>
        /// HttpPost 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string Post(string title, string accessToken, string url, string postdata, string contentType, int retryTimes)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                return Post(accessToken, url, postdata, contentType);
            }, postdata, string.Empty, retryTimes, () => Thread.Sleep(100));
        }
        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string Post(string accessToken, string url, string postdata, string contentType)
        {
            using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(CommonConst.HttpTimeout);
                if (!string.IsNullOrWhiteSpace(accessToken))
                {
                    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
                }
                using (HttpContent httpContent = new StringContent(postdata, Encoding.UTF8))
                {
                    if (!string.IsNullOrWhiteSpace(contentType))
                    {
                        httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
                    }
                    HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
                    var result = response.Content.ReadAsStringAsync().Result;
                    return result;
                }
            }
        }
        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static TResponse Post<TRequest, TResponse>(string title, string url, TRequest request, int retryTimes)
        {
            return RetryHelper.Execute<TResponse>(title, () =>
            {
                return Post<TRequest, TResponse>(url, request);
            }, request, default(TResponse), retryTimes, () => Thread.Sleep(100));
        }

        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <returns></returns>
        public static TResponse Post<TRequest, TResponse>(string url, TRequest request)
        {
            using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(CommonConst.HttpTimeout);
                string postData = string.Empty;
                if (request != null)
                {
                    postData = JsonHelper.SerializeObject(request);
                }
                using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
                {
                    httpContent.Headers.ContentType = new MediaTypeHeaderValue(CommonConst.ContentTypeJson);
                    var response = client.PostAsync(url, httpContent);
                    var result = response.Result.Content.ReadAsAsync<TResponse>().Result;
                    return result;
                }
            }
        }

        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        private static string Post(string url, string postdata, string contentType)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Timeout = 30 * 1000;
            req.Method = "POST";
            req.ContentType = contentType;
            Encoding encoding = Encoding.UTF8;
            byte[] data = encoding.GetBytes(postdata);
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            //获取响应内容  
            string response = string.Empty;
            using (StreamReader reader = new StreamReader(stream, encoding))
            {
                response = reader.ReadToEnd();
                reader.Close();
                stream.Close();
            }
            return response;
        }

        /// <summary>
        /// HttpPost 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string HttpPost(string title, string url, string postdata, string contentType, Encoding encoding, int retryTimes)
        {
            return RetryHelper.Execute<string>(title, () =>
            {
                return Post(url, postdata, contentType, encoding);
            }, postdata, string.Empty, retryTimes, () => Thread.Sleep(100));
        }

        /// <summary>
        /// 发送Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postdata"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        private static string Post(string url, string postdata, string contentType, Encoding encoding)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Timeout = 30 * 1000;
            req.Method = "POST";
            req.ContentType = contentType;
            byte[] data = encoding.GetBytes(postdata);
            req.ContentLength = data.Length;
            using (Stream reqStream = req.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
            //获取响应内容  
            string response = string.Empty;
            using (StreamReader reader = new StreamReader(stream, encoding))
            {
                response = reader.ReadToEnd();
                reader.Close();
                stream.Close();
            }
            return response;
        }
        #endregion

        #endregion

        #region 上传文件
        public static T HttpUploadFile<T>(string url, Encoding encoding, IFormCollection formData, Dictionary<string, string> extDictionary = null)
        {
            using (HttpClient client = new HttpClient())
            {
                client.Timeout = TimeSpan.FromSeconds(CommonConst.HttpTimeout);
                using (MultipartFormDataContent multipartFormDataContent = new MultipartFormDataContent())
                {
                    //装在普通的参数
                    foreach (var item in formData)
                    {
                        multipartFormDataContent.Add(new StringContent(item.Value), item.Key);
                    }
                        

                    //拓展字段参数
                    foreach (var item in extDictionary)
                    {
                        multipartFormDataContent.Add(new StringContent(item.Value), item.Key);
                    }

                    //装载媒体类型参数
                    foreach (var item in formData.Files)
                    {
                        multipartFormDataContent.Add(new StreamContent(item.OpenReadStream()), item.Name, item.FileName);
                    }

                    var response = client.PostAsync(url, multipartFormDataContent).Result;

                    var Result = response.Content.ReadAsAsync<T>().Result;
                    return Result;
                }
            }
        }
        #endregion

    }
}
